const express = require("express");
const multer = require('multer');
const fs = require("fs");
const https = require("https");
const http = require("http");
const app = express();
const jwt = require('jsonwebtoken');
const path = require('path');
const { MongoClient, ObjectId } = require("mongodb");

const blogAPIs = require('./src/blog');
const authAPIs = require('./src/auth');
const mailAPIs = require('./src/mail');
const dashboardAPIs = require('./src/dashboard');
const commentAPIs = require('./src/comment');
const userAPIs = require('./src/user');
const todoAPIs = require('./src/todoList');
const evalAPIs = require('./src/eval');
const worldNewsAPIs = require('./src/worldNews');
const jsEncrypt = require('./src/encrypt.js');
const treasureChestAPIS = require('./src/treasureChest.js');
const sourceAPIS = require('./src/source.js');
const musicAPIS = require('./src/music.js');
const weatherAPIS = require('./src/weather.js');
const { imagesPath, kmyc } = require("./config");
mailAPIs.createMailServer();//开启邮件服务

//文件上传到服务器的位置
const multerInstance = multer({ dest: imagesPath });

const port = process.env.PORT || 3002;

const privateKey = fs.readFileSync("../api_Nginx_SSL/api.hongbin.xyz.key", "utf8");
const certificate = fs.readFileSync(
    "../api_Nginx_SSL/api.hongbin.xyz_bundle.crt",
    "utf8"
);
// const privateKey = fs.readFileSync("../Nginx_SSL/2_hongbin.xyz.key", "utf8");
// const certificate = fs.readFileSync(
//     "../Nginx_SSL/1_hongbin.xyz_bundle.crt",
//     "utf8"
// );
const credentials = { key: privateKey, cert: certificate };

const server = https.createServer(credentials, app);
const httpServer = http.createServer(app);

app.use(multerInstance.any());

// const io = require("socket.io")(httpServer, { cors: true });
const { Server } = require("socket.io");
const io = new Server(process.env.NODE_ENV === "production" ? server : httpServer, { cors: true });

io.on('connection', (socket) => {
    console.log('a user connected', socket.rooms, socket.id);
    socket.on('sendNews', (newNews) => {
        console.log("新消息:", newNews)
        socket.broadcast.emit('haveNewNews', newNews);
    })
});

if (process.env.NODE_ENV === "production") {
    server.listen(port, () => { console.log("> pro mode on https " + port) });
} else {
    httpServer.listen(port, () => { console.log("> dev mode on http " + port) });
}

app.all("*", function (req, res, next) {
    //设置允许跨域的域名，*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin", "*");
    //允许的header类型
    // res.header("Access-Control-Allow-Headers", ["content-type", "Authorization"]);
    res.header("Access-Control-Allow-Headers", "content-type,Authorization");
    //跨域允许的请求方式
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    if (req.method.toLowerCase() == "options") res.status(200).send();
    //让options尝试请求快速结束
    else next();
});

const PATHS = {
    getImage: "/getImage/*",
    kmyc: "/kmyc/*",
    // pokers path
    getPokers: "/getPokers",
    createNewPoker: '/createNewPoker',
    updatePoker: "/updatePoker",
    deletePoker: "/deletePoker",
    // auth path
    getUserByToken: "/getUserByToken",
    checkUsernameValid: "/checkUsernameValid",
    login: "/login",
    register: "/register",
    updateUsername: "/updateUsername",
    updatePassword: "/updatePassword",
    // blog 
    uploadFile_md: '/uploadFile_md',
    releaseBlog: "/releaseBlog",
    getBlogs: "/getBlogs",
    getAllBlogTags: '/getAllBlogTags',
    getBlogById: '/getBlogById',
    deleteBlog: "/deleteBlog",
    thumbsUpBlog: "/thumbsUpBlog",
    thumbsDownBlog: "/thumbsDownBlog",
    queryBlogThumbsState: "/queryBlogThumbsState",
    cancelThumbs: "/cancelThumbs",
    transformThumbs: "/transformThumbs",
    // mail
    sendMailCode: '/sendMailCode',
    verificationMailCode: '/verificationMailCode',
    // dashboard
    getAllBrowseCounts: '/getAllBrowseCounts',
    getBlogCounts: "/getBlogCounts",
    getBlogTagsCounts: "/getBlogTagsCounts",
    getPokerCounts: "/getPokerCounts",
    getAllAccountCounts: "/getAllAccountCounts",
    getAllCommentCounts: "/getAllCommentCounts",
    getAllThumbsUpCounts: "/getAllThumbsUpCounts",
    getDashboardData: "/getDashboardData",
    // time task
    createTimeTask: '/createTimeTask',
    deleteTimeTask: '/deleteTimeTask',
    updateTimeTask: '/updateTimeTask',
    queryTimeTaskByMail: '/queryTimeTaskByMail',
    //comment
    sendComment: '/sendComment',
    getCommentByBlog: '/getCommentByBlog',
    thumbsComment: '/thumbsComment',
    cancelThumbsComment: '/cancelThumbsComment',
    transformThumbsComment: '/transformThumbsComment',
    queryComment: "/queryComment",
    deleteComment: "/deleteComment",
    violationComment: "/violationComment",
    //user
    getUserById: '/getUserById',
    queryUser: '/queryUser',
    updateUserRole: '/updateUserRole',
    //_ todoList
    getTodoList: '/getTodoList',
    addTodo: "/addTodo",
    deleteTodo: "/deleteTodo",
    updateTodo: "/updateTodo",
    //eval  js
    getEval: '/getEval',
    //world news
    sendWorldNews: "/sendWorldNews",
    queryWorldNews: "/queryWorldNews",
    //treasureChest
    queryTreasureChest: '/queryTreasureChest',
    // sourceAPIS
    createSource: "/createSource",
    querySource: "/querySource",
    downloadSource: "/downloadSource/*",
    deleteSource: "/deleteSource",
    updateSource: "/updateSource",
    //music 
    getMusic: "/getMusic/*",
    getMusicInfo: "/getMusicInfo",
    queryWeather: '/queryWeather'
}

const ROLE = { 0: "tourist", 1: "manager", 2: 'admin' }

const validAuthorization = async (authorization, role, res, path) => {
    let result = undefined;
    try {
        result = await decrypt(authorization);
        // console.log("validAuthorization:", result);
        if (result.role < role) {
            console.log(`用户${result.username}执行${path}权限不足,当前权限:${result.role}`);
            result = undefined;
            //401 unauthorized，表示发送的请求需要有通过 HTTP 认证的认证信息
            //403 Forbidden：服务器拒绝该次访问（访问权限出现问题）
            res.status(403).send({ message: "权限不够,可联系管理员添加权限" })
        }
    } catch (error) {
        console.error("valid filed:", error);
        res.status(444).send({ message: "jwt错误 authorization验证失败" })
    }
    return result;
}

/*
    key: 请求路径 PATHS 从中取
    value: role级别即执行操作所需的最低权限
*/

const authorityRequest = {
    [PATHS.createNewPoker]: 1, [PATHS.updatePoker]: 1, [PATHS.deletePoker]: 1, [PATHS.uploadFile_md]: 1, [PATHS.releaseBlog]: 1, [PATHS.deleteBlog]: 1, [PATHS.updateUsername]: 0, [PATHS.updatePassword]: 0,
    [PATHS.sendComment]: 0, [PATHS.sendWorldNews]: 0, [PATHS.deleteComment]: 2, [PATHS.violationComment]: 2,
    [PATHS.updateUserRole]: 2, [PATHS.createSource]: 0, [PATHS.deleteSource]: 1, [PATHS.updateSource]: 1,
    [PATHS.addTodo]: 2, [PATHS.deleteTodo]: 2, [PATHS.updateTodo]: 2,
};

app.all("*", async (req, res, next) => {
    const { path, headers: { authorization } } = req;
    const needAuth = Object.keys(authorityRequest).includes(path);

    if (needAuth) {
        const userInfo = await validAuthorization(authorization, authorityRequest[path], res, path);
        if (userInfo) { req.userInfo = userInfo; next(); };
    } else next();
})
//尝试 对post请求进行解析后返回省去下面函数每次都 ondata onend
const postPath = [
    PATHS.transformThumbs, PATHS.sendComment, PATHS.thumbsComment, PATHS.cancelThumbsComment, PATHS.transformThumbsComment, PATHS.sendWorldNews, PATHS.queryComment, PATHS.deleteComment, PATHS.violationComment, PATHS.queryUser, PATHS.updateUserRole,
    PATHS.createTimeTask, PATHS.deleteTimeTask, PATHS.queryTimeTaskByMail, PATHS.updateTimeTask, PATHS.deleteSource, PATHS.addTodo, PATHS.deleteTodo, PATHS.updateTodo,
];

app.post('*', (req, res, next) => {
    if (postPath.includes(req.path)) {
        let payload = '';
        req.on('data', (chunk) => payload += chunk);
        req.on("end", () => {
            req.payload = JSON.parse(payload);
            next();
        })
    } else next();
})

const options = {
    host: "159.75.22.82",
    port: "27017",
    db_name: "mywebsite",
};

const MongoClientConfig = {
    useUnifiedTopology: true,
    auth: {
        username: "hongbin",
        password: "Hongbin",
    },
};

const url = `mongodb://${options.host}:${options.port}/${options.db_name}`;

const client = new MongoClient(url, MongoClientConfig);
client.connect(async err => {
    if (err) console.log("数据库连接失败", err)
    else console.log("数据库连接成功👏")
});
const mongoClient = client.db();

// 密钥 可用文件保存 获取时 fs 读取文件获取
const secret = 'token_secret_123';

const encrypt = (data, time = '30d') => {
    //expiresIn :  15d  2h
    return jwt.sign(data, secret, { expiresIn: time })
}

const decrypt = (token) => jwt.verify(token, secret);

app.get(PATHS.getImage, function (req, res) {
    const imageName = req.url.replace('\/getImage\/', '');
    console.log("getImage:", imageName)

    res.sendFile(imagesPath + imageName);
});

app.get(PATHS.kmyc, function (req, res) {
    const imageName = req.url.replace('\/kmyc\/', '');
    console.log("kmyc:", imageName)

    res.sendFile(kmyc + imageName);
});

app.get(PATHS.getPokers, async (req, res) => {
    const result = await client
        .db() //使用传入的库名 也可传参别的数据库名
        .collection("poker") // 选择表/集合
        .find() //全部数据
        .sort({ level: -1 })
        .toArray(); //Promise

    res.send(result);
});

async function insertOne(collection, data) {
    return await mongoClient.collection(collection).insertOne(data)
        .then((res) => res)
        .catch((err) => { console.log("insertOne fail:", err) });
}
async function aggregate({ collection, pipeline }) {
    return await mongoClient.collection(collection).aggregate(pipeline).toArray()
    // .then((res) => res)
    // .catch((err) => { console.log("aggregate fail:", err) });
}
//cusFilter 覆盖 _id 以满足普通 _id查找不足的情况  cusData同样
async function updateOne({ collection, _id, cusFilter, data, cusData }) {
    return await mongoClient.collection(collection).updateOne(cusFilter || { _id: ObjectId(_id) }, cusData || { $set: data })
        .then((res) => res)
        .catch((err) => { console.log("updateOne fail:", err) });
}

async function deleteOne(collection, _id) {
    return await mongoClient.collection(collection).deleteOne({ _id: ObjectId(_id) })
        .then((res) => res)
        .catch((err) => { console.log("deleteOne fail:", err) });
}

const findData = async ({ collection, find = {}, project = {}, sort = {}, limit = 20, skip = 0 }) =>
    await mongoClient.collection(collection)
        .find(find).project(project).sort(sort).limit(limit).skip(skip).toArray();

const getCollectionCounts = async ({ collection, find = {} }) => await mongoClient.collection(collection).countDocuments(find);

//comment api 
app.post(PATHS.sendComment, commentAPIs[PATHS.sendComment.replace('/', '')](insertOne, updateOne, deleteOne));
app.post(PATHS.thumbsComment, commentAPIs[PATHS.thumbsComment.replace('/', '')](updateOne));
app.post(PATHS.cancelThumbsComment, commentAPIs[PATHS.cancelThumbsComment.replace('/', '')](updateOne));
app.post(PATHS.transformThumbsComment, commentAPIs[PATHS.transformThumbsComment.replace('/', '')](updateOne));
app.get(PATHS.getCommentByBlog, commentAPIs[PATHS.getCommentByBlog.replace('/', '')](aggregate));
app.post(PATHS.queryComment, commentAPIs[PATHS.queryComment.replace('/', '')](aggregate, getCollectionCounts));
app.post(PATHS.deleteComment, commentAPIs[PATHS.deleteComment.replace('/', '')](deleteOne));
app.post(PATHS.violationComment, commentAPIs[PATHS.violationComment.replace('/', '')](updateOne));

//blog api
app.post(PATHS.uploadFile_md, blogAPIs[PATHS.uploadFile_md.replace('/', '')]);
app.post(PATHS.releaseBlog, blogAPIs[PATHS.releaseBlog.replace('/', '')]({ findData, insertOne, updateOne }));
app.post(PATHS.deleteBlog, blogAPIs[PATHS.deleteBlog.replace('/', '')](deleteOne, updateOne));
app.post(PATHS.thumbsUpBlog, blogAPIs[PATHS.thumbsUpBlog.replace('/', '')](updateOne));
app.post(PATHS.thumbsDownBlog, blogAPIs[PATHS.thumbsDownBlog.replace('/', '')](updateOne));
app.post(PATHS.cancelThumbs, blogAPIs[PATHS.cancelThumbs.replace('/', '')](updateOne));
app.post(PATHS.transformThumbs, blogAPIs[PATHS.transformThumbs.replace('/', '')](updateOne));
app.get(PATHS.getBlogs, blogAPIs[PATHS.getBlogs.replace('/', '')](aggregate, getCollectionCounts, decrypt));
app.get(PATHS.getAllBlogTags, blogAPIs[PATHS.getAllBlogTags.replace('/', '')](findData));
app.get(PATHS.getBlogById, blogAPIs[PATHS.getBlogById.replace('/', '')](aggregate, updateOne));
app.get(PATHS.queryBlogThumbsState, blogAPIs[PATHS.queryBlogThumbsState.replace('/', '')](findData));
//auth api 
app.post(PATHS.updateUsername, authAPIs[PATHS.updateUsername.replace('/', '')]({ findData, updateOne, encrypt }));
app.post(PATHS.updatePassword, authAPIs[PATHS.updatePassword.replace('/', '')]({ findData, updateOne, encrypt }));
// mail api
app.post(PATHS.sendMailCode, mailAPIs[PATHS.sendMailCode.replace('/', '')]({ findData }));
app.post(PATHS.verificationMailCode, mailAPIs[PATHS.verificationMailCode.replace('/', '')]({ encrypt, updateOne, decrypt }));
//dashboard api
app.get(PATHS.getAllBrowseCounts, dashboardAPIs[PATHS.getAllBrowseCounts.replace('/', '')](aggregate))
app.get(PATHS.getBlogCounts, dashboardAPIs[PATHS.getBlogCounts.replace('/', '')](getCollectionCounts))
app.get(PATHS.getBlogTagsCounts, dashboardAPIs[PATHS.getBlogTagsCounts.replace('/', '')](getCollectionCounts))
app.get(PATHS.getPokerCounts, dashboardAPIs[PATHS.getPokerCounts.replace('/', '')](getCollectionCounts))
app.get(PATHS.getAllAccountCounts, dashboardAPIs[PATHS.getAllAccountCounts.replace('/', '')](getCollectionCounts))
app.get(PATHS.getAllCommentCounts, dashboardAPIs[PATHS.getAllCommentCounts.replace('/', '')](getCollectionCounts))
app.get(PATHS.getAllThumbsUpCounts, dashboardAPIs[PATHS.getAllThumbsUpCounts.replace('/', '')](aggregate))
app.get(PATHS.getDashboardData, dashboardAPIs[PATHS.getDashboardData.replace('/', '')]({ findData }))
//定时任务 每晚12点统计数据
// dashboardAPIs.scheduleJob({ getCollectionCounts, aggregate, findData, insertOne });
//重复任务
// dashboardAPIs.startTimeTask(findData, mailAPIs.sendMail);
app.post(PATHS.createTimeTask, dashboardAPIs[PATHS.createTimeTask.replace('/', '')](insertOne))
app.post(PATHS.deleteTimeTask, dashboardAPIs[PATHS.deleteTimeTask.replace('/', '')](deleteOne))
app.post(PATHS.queryTimeTaskByMail, dashboardAPIs[PATHS.queryTimeTaskByMail.replace('/', '')](findData))
app.post(PATHS.updateTimeTask, dashboardAPIs[PATHS.updateTimeTask.replace('/', '')](updateOne))
// user 
app.get(PATHS.getUserById, userAPIs[PATHS.getUserById.replace('/', '')](findData, getCollectionCounts));
app.post(PATHS.queryUser, userAPIs[PATHS.queryUser.replace('/', '')](findData, getCollectionCounts));
app.post(PATHS.updateUserRole, userAPIs[PATHS.updateUserRole.replace('/', '')](updateOne));
//_ todo
app.get(PATHS.getTodoList, todoAPIs[PATHS.getTodoList.replace('/', '')](findData));
app.post(PATHS.addTodo, todoAPIs[PATHS.addTodo.replace('/', '')](insertOne));
app.post(PATHS.deleteTodo, todoAPIs[PATHS.deleteTodo.replace('/', '')](deleteOne));
app.post(PATHS.updateTodo, todoAPIs[PATHS.updateTodo.replace('/', '')](updateOne));
// eval
app.get(PATHS.getEval, evalAPIs[PATHS.getEval.replace('/', '')](findData));
//world news
app.post(PATHS.sendWorldNews, worldNewsAPIs[PATHS.sendWorldNews.replace('/', '')](insertOne))
app.post(PATHS.queryWorldNews, worldNewsAPIs[PATHS.queryWorldNews.replace('/', '')](aggregate))
// treasureChest
app.get(PATHS.queryTreasureChest, treasureChestAPIS[PATHS.queryTreasureChest.replace('/', '')](findData));
// sourceAPIS
app.post(PATHS.createSource, sourceAPIS[PATHS.createSource.replace('/', '')](insertOne))
app.get(PATHS.querySource, sourceAPIS[PATHS.querySource.replace('/', '')](aggregate))
app.get(PATHS.downloadSource, sourceAPIS['downloadSource'])
app.post(PATHS.deleteSource, sourceAPIS[PATHS.deleteSource.replace('/', '')](findData, deleteOne))
app.post(PATHS.updateSource, sourceAPIS[PATHS.updateSource.replace('/', '')](findData, updateOne))
// music api
app.get(PATHS.getMusic, musicAPIS['getMusic']);
app.get(PATHS.getMusicInfo, musicAPIS[PATHS.getMusicInfo.replace('/', '')]);
app.get(PATHS.queryWeather, weatherAPIS[PATHS.queryWeather.replace('/', '')]);

//Pokers api
app.post(PATHS.deletePoker, (req, res) => {
    let id = "";
    req.on('data', (data) => {
        id += data;
    })
    req.on('end', () => {
        const _id = ObjectId(id);
        mongoClient.collection("poker").deleteOne({ _id }, (err, result) => {
            if (err) res.status(500);
            console.log("delete success:", result);
            res.send("delete ok");
        });
    })
})

app.get(PATHS.getUserByToken, async (req, res) => {
    const { jwt } = req.query;
    // console.log("解析 jwt :", jwt);
    if (jwt) {
        const payload = { status: false };
        try {
            const user = decrypt(jwt);
            // console.log("解析 jwt :", user);
            //对比数据库中用户 
            const [{ lastUpdate }] = await findData({ collection: 'userProfile', find: { _id: ObjectId(user._id) } });
            const accountNotHaveChanged = user.lastUpdate === lastUpdate;
            // 没有变化 返回 
            if (accountNotHaveChanged) {
                payload['status'] = true;
                payload['user'] = user;
                console.log(user);
            } else {
                //有变化 重新登陆
                payload['message'] = '账号信息有变化,请重新登陆';
            }
        } catch (error) {
            console.log("jwt decrypt error:", error);
            payload['message'] = 'jwt解析错误';
        }
        res.send(payload);
    }
})

//是否有这个用户名
app.get(PATHS.checkUsernameValid, async (req, res) => {
    const { username } = req.query
    console.log(username);
    const result = await mongoClient.collection("userProfile").find({
        username
    }).toArray()
    if (result.length === 0) {
        res.send(true);
    } else res.send(false);
})

app.post(PATHS.login, (req, res) => {
    let params = "";
    req.on('data', (data) => {
        params += data;
    })
    req.on('end', async () => {
        const { username, password } = JSON.parse(params);
        //用户名 密码是否匹配
        const result = await mongoClient.collection("userProfile").find({
            username
        }).toArray()
        if (result.length) {
            const [{ password: dbPassword, ...dbUser }] = result;
            //匹配
            console.log("ok:", dbUser);
            if (dbPassword === jsEncrypt.decrypt(password)) {
                //生成 新的jwt返回
                const jwt = encrypt(dbUser);
                res.json({ newUser: dbUser, jwt, message: '登陆成功' });
            } else res.status(404).json({ message: '密码错误' });
        } else res.status(404).json({ message: '用户名名错误🙅‍♂️' });
    })
})

app.post(PATHS.register, (req, res) => {
    let params = "";
    req.on('data', (data) => {
        params += data;
    })
    req.on('end', async () => {
        let { username, password } = JSON.parse(params);
        password = jsEncrypt.decrypt(password);
        //在前端判断是否有这个用户名 只允许新用户民进入注册功能代码
        //注册 要求 通过注册页面注册的用户只能是游客 管理者需要admin创建
        const insert = { username, role: 0, lastUpdate: Date.now(), thumbsUp: [], thumbsDown: [] };
        const result = await insertOne('userProfile', { password, ...insert });
        console.log(`新用户${username}密码为${password} 注册${result ? "成功" : "失败 "}`, result);
        if (result && result.insertedId) {
            //生成 新的jwt返回 
            const userInfo = { _id: result.insertedId, ...insert };
            const jwt = encrypt(userInfo);
            res.json({ newUser: userInfo, jwt, message: '注册成功' });
        } else res.status(556).json('注册失败');
    })
})

app.post(PATHS.updatePoker, async (req, res) => {
    let params = "";
    req.on('data', (data) => {
        params += data;
    })
    req.on('end', async () => {
        const updateItems = JSON.parse(params);
        console.log(updateItems);

        const handleUpdate = async () => {
            const { _id, ...items } = updateItems;
            console.log(updateItems);
            const result = await updateOne({ collection: 'poker', _id, data: items });
            console.log(result);
            if (!result) {
                res.status(500);
            }
            res.send(updateItems);
        }

        if (updateItems.images) {
            let length = 0;
            updateItems.images.forEach((base64_URL, index) => {
                //如果是 ****.png 格式则不处理
                if (base64_URL.substring(0, 50).indexOf(".png") !== -1) {
                    length++;
                    if (length === updateItems.images.length) {
                        handleUpdate();
                    }
                    return;
                };
                const base64 = base64_URL.replace(/^data:image\/\w+;base64,/, "");
                const imageName = `${Date.now()}${index}.png`;
                const path = `${imagesPath}${imageName}`;
                fs.writeFile(path, base64, 'base64', async function (err) {
                    if (err) {
                        console.log(err);
                        res.status(500);
                    } else {
                        updateItems.images[index] = imageName;
                        length++;
                        if (length === updateItems.images.length) {
                            //图片处理完毕
                            await handleUpdate();
                        }
                    }
                })
            })
        } else await handleUpdate();
    })
})

app.post(PATHS.createNewPoker, (req, res) => {
    let params = "";
    req.on('data', (data) => {
        params += data;
    })
    req.on('end', () => {
        const poker = JSON.parse(params);
        let length = 0;
        const imagePaths = [];
        poker.images.forEach((base64_URL, index) => {
            const base64 = base64_URL.replace(/^data:image\/\w+;base64,/, "");
            const imageName = `${Date.now()}${index}.png`;
            const path = `${imagesPath}${imageName}`;
            fs.writeFile(path, base64, 'base64', async function (err) {
                if (err) {
                    console.log(err);
                    res.status(404).send('Sorry, cant find that');
                } else {
                    console.log('写入成功！', path)
                    imagePaths.push(imageName);
                    length++;
                    if (length === poker.images.length) {
                        console.log("poker:", poker);
                        const pokerItem = { ...poker, images: imagePaths };
                        const result = await insertOne('poker', pokerItem);
                        if (!result) {
                            res.status(404).send('Sorry, cant find that');
                        }
                        console.log("poker item:", result.insertedId);
                        res.send({ ...pokerItem, _id: result.insertedId });
                    }
                }
            });
        })
    })
})


//查
app.get("/getTodoLists", async (req, res) => {
    const result = await mongoClient.collection("todoList").find().toArray();
    console.log("result:", result);

    res.send(result);
});
//增
app.post("/addTodo", (req, res) => {
    let params = "";
    req.on("data", data => {
        params += data;
    });
    req.on("end", async () => {
        const { content, reminderTime } = JSON.parse(params);

        const data = {
            content,
            status: false,
            reminderTime: new Date(reminderTime),
        };

        try {
            const {
                ops: [todo],
            } = await mongoClient.collection("todoList").insertOne(data);
            console.log(todo);
            res.send(todo);
        } catch (error) {
            console.error("addTodo:", error);
            res.status(500);
        }
    });
});
//删
app.post("/deleteTodoItem", (req, res) => {
    let params = "";
    req.on("data", data => {
        params += data;
    });
    req.on("end", () => {
        const { id } = JSON.parse(params);
        client
            .db()
            .collection("todoList")
            .deleteOne({ _id: ObjectId(id) }, (err, result) => {
                if (err) res.status(500);
                console.log("delete success:", result);
                res.send("ok");
            });
    });
});

//改
app.post("/toggleTodoState", (req, res) => {
    let params = "";
    req.on("data", data => {
        params += data;
    });
    req.on("end", () => {
        const { id, status } = JSON.parse(params);
        console.log(id, status);
        client
            .db()
            .collection("todoList")
            .updateOne({ _id: ObjectId(id) }, { $set: { status } }, (err, result) => {
                if (err) res.status(500);
                if (result.result.n === 1) {
                    res.send("ok");
                }
            });
    });
});

app.get("/", (req, res, next) => {
    return res.redirect(302, 'https://kmyc.hongbin.xyz');
    let pathName = req.url;
    console.log(pathName);
    // 提供一个 icon就不会发起/favicon.ico的请求了
    if (pathName == "/") {
        pathName = "/index.html";
    }

    const extName = path.extname(pathName);
    fs.readFile(`${__dirname}/public/kmycdemo${pathName}`, function (err, data) {
        if (err) {
            console.error(err);
            res.status(400).json(err);
        } else {
            const ext = getExt(extName);
            res.writeHead(200, { "Content-Type": ext + "; charset=utf-8" });
            res.write(data);
        }
        res.end();
    });
});

const EXT = {
    ".html": "text/html",
    ".css": "text/css",
    ".js": "text/js",
    ".ico": "image/x-icon",
    ".png": "image/png",
};
// 获取后缀名
getExt = extName => {
    return EXT[extName];
};
